#!/home/timm/opt/gawk/bin/gawk -f 
 
# lib.awk
# Revision: 297
# Built by timm on Sat Jul 30 20:59:55 PDT 2011.

#   _ _ _                                               ((
#  |=|=|=|.----------------------------------------.    _))_
#  |-|-|-|| AWK code of a tiny book on data mining | ___\__/)_
#  |_|_|_|'----------------------------------------| |_|_~~_|_|

# This file is part of TINY.
#
# TINY is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# TINY is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
#  along with TINY.  If not, see <http://www.gnu.org/licenses/>.

 BEGIN { 
         _ = SUBSEP 
         Q = "\"" 
         Pi= 3.1415926535
         Ee= 2.7182818284 
         Inf=10^32
         Pinch=1/Inf
       }
 function resetSeed(    seed) {
	if (seed) return(srand(seed))
	if(Seed)  return(srand(Seed))
	return srand(systime() + PROCINFO["pid"]) 
 }
 function sum(a, n,i) {
     for(i in a) n += a[i]
     return n
 }

 ; sorts a[key]=value pairs
 function a2cdf(a,cdf,    some,n,i,j,sum,memo) {
     for(i in a) {
	 some  = rand() * Pinch
	 a[i] += Pinch
	 memo[a[i]] = i
     }
    cdf[0] = n = asort(a,sorted)
    sum = cdf[1] = sorted[1];
    for(i=2;i<=length(sorted);i++) { 
        sum += sorted[i];
        cdf[i] = cdf[i-1] + sorted[i];
    }
    for(i in cdf)  
        cdf[i] = cdf[i] / sum
    for(i=1;i<=n;i++)
        cdf[-1*i] = memo[sorted[i]]
 }
 function pick(cdf,   i) {
    i = pick1(cdf,rand(),cdf[0])
    return cdf[-1*i]
 }
 function pick1(cdf,u,n,  u,i) {
    for(i=n-1;i>=1;i--) if (u > cdf[i]) return i+1;
    return 1;
 }	 
 function norm(x,min,max) { 
 	return (x - min)/ (max - min + Pinch) 
 }
 function stddev(n,sum,sumSq,   tmp) {
    tmp = (sumSq-((sum*sum)/n))/(n-1)
	tmp = tmp < 0 ? 0 : tmp
   return sqrt(tmp)
 }
 function gaussianPdf(m,s,x) {
    s = s + Pinch
    return 1/sqrt(2*Pi*s^2)*Ee^(-1*(x-m)^2/(2*s^2))
 }
 function round(x)      { 
	return int(x<0 ? x-0.5 : x+0.5) 
 }
 function abs(n) { return n < 0 ? -1*n : n }
 function odd(n) { return n % 2 } 
 function even(n) { return (n % 2) + 1 } 
 function median(a0,    sorted,a,n,half) {
	if (!sorted)  { asort(a0,a); return median(a,1) }
	half = int(n/2) 
	return odd(n) ? a[half] : (a[half] + a[half+1])/2 
  }
 function array(a) {
	split("",a)
  }
 function push(a,v,old) {
 	old      = length(a)
 	a[old+1] = v
 	return v
 }
 function pop(a,  old,v) {
 	old = length(a)
	v   = a[old]
	delete a[old]
	return v
 }
 function pretty(x) {
	gsub(_,",",x)
    return x
 }
 function trim(x) {
	sub(/^[ \t]*/,"",x)
	sub(/[ \t]*$/,"",x)
	return x
 }
 function o(a, str,control, i,com) {
      str = str ? str : "array"
      com = control ? control : " -n  -k 2" 
      com = "sort " com  " #" rand(); # ensure com is unique
      for(i in a) print oprim(str,i,a) | com;
      close(com) 
  }
 function oprim(str,i,a,  j) {
      j=i
      gsub(SUBSEP,",",j) 
      return str "[ " j " ]\t=\t [ " a[i] " ]"
 }
 function p2a(pairs,a,   sep,blankp,     n,tmp,i) {
	sep = sep ? sep : "/,/"
	n=split(pairs,tmp,sep)
	if (!blankp) 
		for(i in tmp) 
			tmp[i]=trim(tmp[i])
	for(i=1;i<=n;i=i+2) 
		a[tmp[i]] = tmp[i+1] 
 }
 function rank(data0,ranks,     \
               data,starter,n,old,start,skipping,sum,i,j,r) {
     starter="someCraZYsymBOL";
     n     = asort(data0,data)    
     old   = starter
     start = 1;
     delete ranks;
     for(i=1;i<=n;i++) {
	 skipping = (old == starter) || (data[i] == old);
	 if (skipping) {
	     sum += i 
	 } else {
	     r = sum/(i - start)
	     for(j=start;j<i;j++) 
		 ranks[data[j]] = r;
	     start = i;
	     sum   = i;
	 }
	 old=data[i]
     }
     if (skipping) {
	 ranks[data[n]] = sum/(i - start)
     } else {
	 if (! (data[n] in ranks))
	     ranks[data[n]] = n #int(r+1.4999)
     }
 }
 function criticalValue(conf) {
     conf = conf ? conf  : 95
     if (conf==99) return 2.326
     if (conf==95) return 1.960 
     if (conf==90) return 1.645
 }
 function minMax(col,x,missing,min,max) {
    if(x == missing) return 1
	if(col in min) {if(x < min[col]) {min[col]=x}} else {min[col]=x}
	if(col in max) {if(x > max[col]) {max[col]=x}} else {max[col]=x}
}
 function readHeader(col,x,       name,indx,num,sym,dep,indep,	\
                                  ignorep,nump,depp) {
	ignorep    = gsub(/\?/,"",x) 
	nump       = gsub(/\$/,"",x)
	depp       = gsub(/\!/,"",x) 
	indx[x]    = col
	name[col]  = x
	if (!ignorep)  {
		nump ? num[col] : sym[col]
		depp ? dep[col] : indep[col]
}}
 function discretize(col,rows,data,bins,want1,b1,c1,want2,b2,c2,\
                        all,n,row,sorted) {
    for(row=1;row<=rows;row++)  
	all[row] = data[row,col]
    n    = asort(all,sorted)
    if(want1) efd(col,sorted,n,bins,b1,c1)
    if(want2) ewd(col,sorted,n,bins,b2,c2)
}
function efd(col,sorted,n,bins,b,c,   row,all,bin,i,jump,last) {
    bin  = last = 0
    i = jump = int(n/bins)
    while(i < n) {
	if (sorted[i] == sorted[i+1]) {
	    i++
        } else {
	    bin++
	    b[col,bin] = sorted[i]
	    c[col,bin] = i - last
	    last = i
	    i += jump }}
    if ((n-last) > (c[col,bin]/2)) 
	bin++
    b[col,bin] = sorted[n]
    c[col,bin] += n - last
}
function ewd(col,sorted,n,bins,b,c,       min,max,jump,i,j) {
    min  = sorted[1]
    max  = sorted[n]
    jump = (max - min)/bins + 0.00000001
    for(i=1;i<=bins;i++)
	b[col,i] = min + round(i* jump)
    j=1
    for(i=1;i<=n;i++) {
	if(sorted[i]> b[col,j]) j++
	c[col, j]++
    }
}
function asBin(col,x,bins,breaks,  bin) {
    for(bin=1;bin<=bins;bin++)
	if ((col,bin) in breaks)
	    if (x <= breaks[col,bin])
		return bin
    return 1
}
function nchars(n,char,   out) {
    while(n> 0) {n--; out = out char}
    return out
}
function fyi(x) {
    print "#FYI: " x >>"/dev/stderr"
}

